package cn.wolfcode.aspect;

import cn.wolfcode.domain.Log;
import cn.wolfcode.mapper.LogMapper;
import cn.wolfcode.util.ParameterMapUtil;
import cn.wolfcode.util.RequestUtil;
import cn.wolfcode.util.RequirePermission;
import cn.wolfcode.util.UserContext;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.apache.ibatis.javassist.ClassClassPath;
import org.apache.ibatis.javassist.ClassPool;
import org.apache.ibatis.javassist.CtClass;
import org.apache.ibatis.javassist.CtMethod;
import org.apache.ibatis.javassist.bytecode.CodeAttribute;
import org.apache.ibatis.javassist.bytecode.LocalVariableAttribute;
import org.apache.ibatis.javassist.bytecode.MethodInfo;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;
import java.util.*;

//@Component //把当前类注入到spring容器中
//@Aspect    //把当前类标识为一个切面供容器读取
public class AopConfig {

    @Autowired
    private LogMapper logMapper;
    /**
     * 指定切入点
     * 对贴有自定义注解@RequiredPermission的方法，进行切面
     */

    @Pointcut("@annotation(cn.wolfcode.util.RequirePermission)")
    private void useMethod() {


    }


    /**
     * 对切入点进行增强
     */
    @Around(value = "useMethod()")
    public Object recordLog(ProceedingJoinPoint joinPoint) throws Throwable {
        //获取方法里的权限名臣和内容
        //执行处理方法（执行控制器中的方法）
        Log log = new Log();
        log.setUsername(UserContext.getCurrentEmployee().getUsername());

        long startTime = System.currentTimeMillis();    //获取开始时间

        Date date = new Date();//操作时间
        log.setOperation_time(date);
        Object target = null;
        String error = "无";
        try {
            target = joinPoint.proceed();
            log.setResult(true);
        } catch (Throwable throwable) {
            error = throwable.getMessage();
            log.setResult(false);
        }
        log.setError_info(error);

        long endTime = System.currentTimeMillis();    //获取结束时间
        Long carryTime = endTime - startTime;  //获取方法执行时间
        System.out.println("执行时间:"+carryTime);
        log.setCarry_time(carryTime);

        //获取当前方法类名
        String name = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        String requestMethod = name+":"+methodName;
        System.out.println("执行方法："+requestMethod);
         log.setRequest_method(requestMethod);


        //获取ip
        HttpServletRequest request2 = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();//获取request
        String url = request2.getRequestURI();
        System.out.println("IP地址："+RequestUtil.getIpAddress(request2));
        log.setIp(RequestUtil.getIpAddress(request2));

        Signature sig = joinPoint.getSignature();
        MethodSignature msig =(MethodSignature) sig;
        Method method = msig.getMethod();
        String operationMoudle = null;
        if (method!=null){
            //得到方法上此注解的信息
            String name2 = method.getAnnotation(RequirePermission.class).name();
            operationMoudle = name2;
        }
        System.out.println("模块："+operationMoudle);
        log.setOperation_module(operationMoudle);


         //通过joinPoint.getArgs()获取Args参数
//        String queryString = request2.getQueryString();
        Map map = ParameterMapUtil.getParameterMap(request2);

       log.setRequest_param(JSON.toJSONString(map));
        System.out.println(log);
        logMapper.insert(log);
        return target;
    }






}